package asm;

import aj.org.objectweb.asm.ClassVisitor;

/**
 * 概念
 * 1、可以使用java的汇编语言操作， 等同于在c里面操作汇编 __asm__。 只是这里操作的是java的汇编。
 * 2、java 汇编 java class 文件解释 https://juejin.cn/post/6844903574812491784
 * ClassFile {
 *    u4             magic;
 *    u2             minor_version;
 *    u2             major_version;
 *    u2             constant_pool_count;
 *    cp_info        constant_pool[constant_pool_count-1];
 *    u2             access_flags;
 *    u2             this_class;
 *    u2             super_class;
 *    u2             interfaces_count;
 *    u2             interfaces[interfaces_count];
 *    u2             fields_count;
 *    field_info     fields[fields_count];
 *    u2             methods_count;
 *    method_info    methods[methods_count];
 *    u2             attributes_count;
 *    attribute_info attributes[attributes_count];
 * }
 * 字节u4 前四个 u2 4-6字节.... 如果要透彻明白字节码需要读java虚拟机规范。 阿里【龙井虚拟机】 一手文档去官方找。【class format】
 *
 * 3、查看一个类的二进制 光标进类体-> view -> show bytecode
 *                                   ->  show bytecode with jclasslib 这是插件  同javap的作用。
 * init构造方法 可以看到默认是super()了父辈构造。
 * 如果数据有问题需要把这个类重新编译下 在main里面执行下行了。
 * 可以看到指令的排序的
 * int i = 0;
 * int b = i++;
 *
 * 4、asm的二进制的操作。
 * ClassVisitor 是visitor class文件
 * class 文件有各种各样的 Node 整个class是由不同的node构成的。
 *                     Field
 *                     Method
 *                     Version
 *                     ......
 * 这个class要visitor到每个不同的部分
 * 相当于visitor到了每个部分上
 *
 * ClassWriter生成一个class
 * cw = new ClassWriter(0) 创建一个空的 class文件
 * cw.visitor("写入内容")
 * 一个新的语言要做成一个class就拿asm visitor搞就行了。 asm是动态生成字节码而不是代码。
 * 自定义classloader 直接继承 classLoader就行了重写需要的方法。
 * Class c = myClassLoader.defineClass("xx.xx", cw生成的字节码)
 * c.getMethods[0].getName();
 *
 * 所以asm可以读class文件也可以写  ClassReader【读】  ClassWriter【写】
 *
 *
 * 5、用asm生成动态代理
 * 把一个class 动态改变并生成。
 * byte[] b1; 原来类的字节码  ClassPrinter.class.getClassLoader().getResourceAsStream("xxx.xxx") // 通过类加载器获取二进制流。
 * 1、创建一个空的Class
 * ClassWriter cw = new ClassWriter(0);
 * 2、读取一个class文件
 * ClassReader cr = new ClassReader(b1);
 * 3、cr的读取直接扔到cw上去
 * cr.accept(cw,0);
 * 4、cw转二进制流。
 * cw.toByteArray()
 *
 * 怎么自定义一个ClassVisitor
 * 然后 通过cw憝到cr 上面去。
 *
 * ClassVisitor cv = new ClassVisitor(Asm4 ,cw){
 *  // 在这里生成改变reader的class内容的功能 如果没有cv就是对cr的一个拷贝没有修改任何代码
 * }
 *
 * 其实就是
 * cr 读取完了 被你 cv 截获 然后cv 处理完了 由 cw 生成。 后面一个资源被前一个所使用。
 * 调用
 * cr.accept(cv, 0);
 * 拿到cw.toByteArray() 以后就可以落到磁盘了
 *
 * 最后的过程是
 * cv 访问 reader 处理 结果就是处理操作， 然后最后传给了cw。
 */


public class Asm {
    public static void main(String[] args) {
        System.out.println("asm");
        int ma = 10;
        int mb = ma++;
        System.out.println(mb);

    }
}
